﻿using Ibp.Service.Entity.DEntity;
using Ibp.Service.Entity.ODAEntity;
using OdaOperation.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using Teigha.Core;
using Teigha.TD;

namespace OdaOperation.Utils
{
    public static class OdaExtend
    {
        // 将 OdDbEntity 类型的对象转换为泛型 T 类型的 DEntityBase 对象
        public static T ToDEntity<T>(this OdDbEntity entity, string refLayerName, ulong refLayerId, List<ExportDump> list) where T : DEntityBase, new()
        {
            T expr_05 = Activator.CreateInstance<T>();
            expr_05.Layer = (refLayerName ?? entity.layer());
            expr_05.LayerId = ((refLayerId > 0uL) ? refLayerId : entity.layerId().getHandle().ToUInt64());
            expr_05.RawLayerId = entity.layerId().getHandle().ascii();
            expr_05.LineWidth = (double)((float)entity.lineWeight());
            T t = expr_05;
            t.LineTypeId = entity.linetypeId().getHandle().ToUInt64();
            OdCmColor odCmColor = entity.color();
            if (odCmColor.isByLayer())
            {
                odCmColor = (entity.layerId().openObject() as OdDbLayerTableRecord).color();
            }
            byte b = odCmColor.red();
            byte b2 = odCmColor.green();
            byte b3 = odCmColor.blue();
            t.LineColor = string.Concat(new string[]
            {
            b.ToString(),
            ",",
            b2.ToString(),
            ",",
            b3.ToString()
            });
            t.BlockId = list.LastOrDefault<ExportDump>().BlockId;
            t.Paths = new List<string>();
            foreach (ExportDump current in list)
            {
                t.Paths.Add(current.BlockName ?? "");
                t.Paths.Add(string.Format("{0}", current.Id));
            }
            return t;
        }

        // 将 OdDbPoint 类型的对象转换为 DPoint 对象
        public static DPoint ToDPoint(this OdDbPoint point)
        {
            return new DPoint
            {
                X = point.position().x,
                Y = point.position().y,
                Z = point.position().z
            };
        }

        // 将 OdGePoint2d 类型的对象转换为 DPoint 对象
        public static DPoint ToDPoint(this OdGePoint2d point)
        {
            return new DPoint(point.x, point.y, 0.0);
        }

        // 将 OdGePoint3d 类型的对象转换为 DPoint 对象
        public static DPoint ToDPoint(this OdGePoint3d point)
        {
            return new DPoint(point.x, point.y, point.z);
        }

        // 将 OdGeVector3d 类型的对象转换为 DPoint 对象
        public static DPoint ToDPoint(this OdGeVector3d point)
        {
            return new DPoint(point.x, point.y, point.z);
        }

        // 将 OdDbLine 类型的对象转换为 DLine 对象
        public static DLine ToDLine(this OdDbLine line, string refLayerName, ulong refLayerId, List<ExportDump> list)
        {
            DLine dLine = line.ToDEntity<DLine>(refLayerName, refLayerId, list);
            dLine.Start = line.startPoint().ToDPoint();
            dLine.End = line.endPoint().ToDPoint();
            return dLine;
        }

        // 将 OdDbPolyline 类型的对象转换为 DPolyline 对象
        public static DPolyline ToDPloyLine(this OdDbPolyline polyline, string refLayerName, ulong refLayerId, OdGeMatrix3d transform, OdResult result, List<ExportDump> list)
        {
            // 实例化 DPolyline 对象
            DPolyline dPolyline = polyline.ToDEntity<DPolyline>(refLayerName, refLayerId, list);
            if (dPolyline.Vertexes == null)
            {
                dPolyline.Vertexes = new List<DVertex>();
            }
            if (result == OdResult.eOk)
            {
                // 如果结果为 Ok，则直接添加顶点
                for (uint num = 0u; num < polyline.numVerts(); num += 1u)
                {
                    DVertex dVertex = new DVertex();
                    OdGePoint3d odGePoint3d = new OdGePoint3d();
                    polyline.getPointAt(num, odGePoint3d);
                    dVertex.Bulge = polyline.getBulgeAt(num);
                    dVertex.X = odGePoint3d.x;
                    dVertex.Y = odGePoint3d.y;
                    dVertex.Z = 0.0;
                    dPolyline.Vertexes.Add(dVertex);
                }
            }
            else
            {
                // 否则，通过转换矩阵对顶点进行转换后添加
                for (uint num2 = 0u; num2 < polyline.numVerts(); num2 += 1u)
                {
                    DVertex dVertex2 = new DVertex();
                    OdGePoint3d odGePoint3d2 = new OdGePoint3d();
                    polyline.getPointAt(num2, odGePoint3d2);
                    odGePoint3d2 = odGePoint3d2.transformBy(transform);
                    dVertex2.Bulge = polyline.getBulgeAt(num2);
                    dVertex2.X = odGePoint3d2.x;
                    dVertex2.Y = odGePoint3d2.y;
                    dVertex2.Z = 0.0;
                    dPolyline.Vertexes.Add(dVertex2);
                }
            }
            dPolyline.IsClose = polyline.isClosed();
            return dPolyline;
        }

        // 类似地，还有 ToDPloyLine 方法的重载，针对 OdDb2dPolyline 和 OdDb3dPolyline 类型的对象。
        public static DPolyline ToDPloyLine(this OdDb2dPolyline polyline, string refLayerName, ulong refLayerId, OdGeMatrix3d transform, OdResult result, List<ExportDump> list)
        {
            DPolyline dPolyline = polyline.ToDEntity<DPolyline>(refLayerName, refLayerId, list);
            if (dPolyline.Vertexes == null)
            {
                dPolyline.Vertexes = new List<DVertex>();
            }
            if (result == OdResult.eOk)
            {
                OdDbObjectIterator odDbObjectIterator = polyline.vertexIterator();
                odDbObjectIterator.start();
                while (!odDbObjectIterator.done())
                {
                    OdDbObject odDbObject = odDbObjectIterator.objectId().safeOpenObject();
                    OdDb2dVertex odDb2dVertex = odDbObject as OdDb2dVertex;
                    if (odDb2dVertex != null)
                    {
                        dPolyline.Vertexes.Add(new DVertex
                        {
                            X = odDb2dVertex.position().x,
                            Y = odDb2dVertex.position().y,
                            Z = odDb2dVertex.position().z
                        });
                    }
                    odDbObjectIterator.step();
                }
            }
            else
            {
                OdDbObjectIterator odDbObjectIterator2 = polyline.vertexIterator();
                odDbObjectIterator2.start();
                while (!odDbObjectIterator2.done())
                {
                    OdDbObject odDbObject2 = odDbObjectIterator2.objectId().safeOpenObject();
                    OdDb2dVertex odDb2dVertex2 = odDbObject2 as OdDb2dVertex;
                    if (odDb2dVertex2 != null)
                    {
                        OdGePoint3d odGePoint3d = odDb2dVertex2.position();
                        odGePoint3d = odGePoint3d.transformBy(transform);
                        dPolyline.Vertexes.Add(new DVertex
                        {
                            X = odGePoint3d.x,
                            Y = odGePoint3d.y,
                            Z = odGePoint3d.z
                        });
                    }
                    odDbObjectIterator2.step();
                }
            }
            dPolyline.IsClose = polyline.isClosed();
            return dPolyline;
        }

        public static DPolyline ToDPloyLine(this OdDb3dPolyline polyline, string refLayerName, ulong refLayerId, OdGeMatrix3d transform, OdResult result, List<ExportDump> list)
        {
            DPolyline dPolyline = polyline.ToDEntity<DPolyline>(refLayerName, refLayerId, list);
            if (dPolyline.Vertexes == null)
            {
                dPolyline.Vertexes = new List<DVertex>();
            }
            if (result == OdResult.eOk)
            {
                OdDbObjectIterator odDbObjectIterator = polyline.vertexIterator();
                odDbObjectIterator.start();
                while (!odDbObjectIterator.done())
                {
                    OdDbObject odDbObject = odDbObjectIterator.objectId().safeOpenObject();
                    OdDb3dPolylineVertex odDb3dPolylineVertex = odDbObject as OdDb3dPolylineVertex;
                    if (odDb3dPolylineVertex != null)
                    {
                        OdGePoint3d odGePoint3d = odDb3dPolylineVertex.position();
                        dPolyline.Vertexes.Add(new DVertex
                        {
                            X = odGePoint3d.x,
                            Y = odGePoint3d.y,
                            Z = odGePoint3d.z
                        });
                    }
                    odDbObjectIterator.step();
                }
            }
            else
            {
                OdDbObjectIterator odDbObjectIterator2 = polyline.vertexIterator();
                odDbObjectIterator2.start();
                while (!odDbObjectIterator2.done())
                {
                    OdDbObject odDbObject2 = odDbObjectIterator2.objectId().safeOpenObject();
                    OdDb3dPolylineVertex odDb3dPolylineVertex2 = odDbObject2 as OdDb3dPolylineVertex;
                    if (odDb3dPolylineVertex2 != null)
                    {
                        OdGePoint3d odGePoint3d2 = odDb3dPolylineVertex2.position();
                        odGePoint3d2 = odGePoint3d2.transformBy(transform);
                        dPolyline.Vertexes.Add(new DVertex
                        {
                            X = odGePoint3d2.x,
                            Y = odGePoint3d2.y,
                            Z = odGePoint3d2.z
                        });
                    }
                    odDbObjectIterator2.step();
                }
            }
            dPolyline.IsClose = polyline.isClosed();
            return dPolyline;
        }

        // 将 OdDbArc 类型的对象转换为 DArc 对象
        public static DArc ToDArc(this OdDbArc arc, string refLayerName, ulong refLayerId, List<ExportDump> list)
        {
            DArc dArc = arc.ToDEntity<DArc>(refLayerName, refLayerId, list);
            OdGePoint3d odGePoint3d = new OdGePoint3d();
            OdGePoint3d odGePoint3d2 = new OdGePoint3d();
            OdGePoint3d point = arc.center();
            dArc.Center = point.ToDPoint();
            arc.getStartPoint(odGePoint3d);
            arc.getEndPoint(odGePoint3d2);
            dArc.End = odGePoint3d2.ToDPoint();
            dArc.Start = odGePoint3d.ToDPoint();
            dArc.Normal = arc.normal().ToDPoint();
            dArc.IsClockWise = false;
            return dArc;
        }

        public static DArc ToDArc(this OdDbCircle circle, string refLayerName, ulong refLayerId, List<ExportDump> list)
        {
            DCircle dCircle = circle.ToDEntity<DCircle>(refLayerName, refLayerId, list);
            dCircle.Center = circle.center().ToDPoint();
            OdGePoint3d odGePoint3d = new OdGePoint3d();
            circle.getPointAtParam(0.1, odGePoint3d);
            dCircle.Start = odGePoint3d.ToDPoint();
            dCircle.End = dCircle.Start;
            dCircle.Normal = circle.normal().ToDPoint();
            return dCircle;
        }

        public static DSpline ToDSpline(this OdDbSpline spline, string refLayerName, ulong refLayerId, List<ExportDump> list)
        {
            DSpline dSpline = spline.ToDEntity<DSpline>(refLayerName, refLayerId, list);
            if (dSpline.ControlPoints == null)
            {
                dSpline.ControlPoints = new List<DPoint>();
            }
            OdGePoint3dArray odGePoint3dArray = new OdGePoint3dArray();
            OdGeDoubleArray weights = new OdGeDoubleArray();
            OdGeDoubleArray knots = new OdGeDoubleArray();
            int num;
            bool flag;
            bool flag2;
            bool flag3;
            double num2;
            double num3;
            spline.getNurbsData(out num, out flag, out flag2, out flag3, odGePoint3dArray, knots, weights, out num2, out num3);
            for (int i = 0; i < odGePoint3dArray.Count; i++)
            {
                dSpline.ControlPoints.Add(odGePoint3dArray[i].ToDPoint());
            }
            return dSpline;
        }

        public static DEllipse ToDEllipse(this OdDbEllipse ellipse, string refLayerName, ulong refLayerId, List<ExportDump> list)
        {
            DEllipse dEllipse = ellipse.ToDEntity<DEllipse>(refLayerName, refLayerId, list);
            dEllipse.Center = ellipse.center().ToDPoint();
            dEllipse.MajorAxis = ellipse.majorAxis().ToDPoint();
            dEllipse.MajorRadius = ellipse.majorAxis().length();
            dEllipse.Normal = ellipse.normal().ToDPoint();
            dEllipse.MinorAxis = ellipse.minorAxis().ToDPoint();
            dEllipse.MinorRadius = ellipse.minorAxis().length();
            dEllipse.StartAngle = ellipse.startAngle();
            dEllipse.EndAngle = ellipse.endAngle();
            return dEllipse;
        }

        public static DText ToDText(this OdDbText text, string refLayerName, ulong refLayerId, List<ExportDump> list)
        {
            DText dText = text.ToDEntity<DText>(refLayerName, refLayerId, list);
            OdDbTextStyleTableRecord odDbTextStyleTableRecord = text.textStyle().openObject() as OdDbTextStyleTableRecord;
            dText.Value = text.textString();
            dText.FontFamily = odDbTextStyleTableRecord.getName();
            dText.FontSize = odDbTextStyleTableRecord.textSize();
            dText.Rotation = text.rotation();
            dText.Position = text.position().ToDPoint();
            dText.Width = text.widthFactor();
            dText.Height = text.height();
            dText.TextHorMode = (int)text.horizontalMode();
            dText.TextVertMode = (int)text.verticalMode();
            dText.IsMultiText = false;
            dText.AlignmentPoint = text.alignmentPoint().ToDPoint();
            OdGePoint3dArray odGePoint3dArray = new OdGePoint3dArray();
            text.getBoundingPoints(odGePoint3dArray);
            dText.TopLeft = odGePoint3dArray[0].ToDPoint();
            dText.TopRight = odGePoint3dArray[1].ToDPoint();
            dText.BottomLeft = odGePoint3dArray[2].ToDPoint();
            dText.BottomRight = odGePoint3dArray[3].ToDPoint();
            return dText;
        }

        public static DText ToDText(this OdDbMText text, string refLayerName, ulong refLayerId, List<ExportDump> list)
        {
            DText dText = text.ToDEntity<DText>(refLayerName, refLayerId, list);
            OdDbTextStyleTableRecord odDbTextStyleTableRecord = text.textStyle().openObject() as OdDbTextStyleTableRecord;
            dText.Value = text.contents();
            dText.FontFamily = odDbTextStyleTableRecord.getName();
            dText.FontSize = odDbTextStyleTableRecord.textSize();
            dText.Rotation = text.rotation();
            dText.Position = text.location().ToDPoint();
            dText.Width = text.actualWidth();
            dText.Height = text.actualHeight();
            dText.TextHorMode = (int)text.horizontalMode();
            dText.TextVertMode = (int)text.verticalMode();
            dText.IsMultiText = true;
            OdGePoint3dArray odGePoint3dArray = new OdGePoint3dArray();
            text.getBoundingPoints(odGePoint3dArray);
            dText.TopLeft = odGePoint3dArray[0].ToDPoint();
            dText.TopRight = odGePoint3dArray[1].ToDPoint();
            dText.BottomLeft = odGePoint3dArray[2].ToDPoint();
            dText.BottomRight = odGePoint3dArray[3].ToDPoint();
            return dText;
        }
    }
}
